// Openlayers map object 
var map;

// Geoserver count	
var itemRecords = '';

// Thredds server count: not being used at the moment	
var catalogRecords = ''; 

// Proxy setting for Cross Origin Resource Sharing
OpenLayers.ProxyHost = '';
//OpenLayers.ProxyHost = 'proxy.php?mode=native&url=';

// Stop the pink tiles appearing on error
OpenLayers.Util.onImageLoadError = function() {
	this.style.display = "";
	this.src="images/blank.png";
};

// Retrive Geoserver list Json file 
$.getJSON("serverList.json", { "noCache": new Date().getTime() }, function(data){})
.success(function(data) 
{ 
	localStorage.ACEASportalGeoServerList = JSON.stringify(data);	
	loadServers();
});

// Retrive Thredds catalog list Json file 
$.getJSON("catalogList.json", { "noCache": new Date().getTime() }, function(data){})
.success(function(data) 
{ 
	localStorage.ACEASportalThreddsCatalogList = JSON.stringify(data);	
	loadCatalogs();
});

// Reset map action when browser window being resized 
$(window).resize(function() 
{
	resetMapDiv();
});

// Extract server list from localstorage and getCapability of the each server
// Update localstorage with getCapabilty data
function loadServers()
{
	var serverList = (typeof localStorage.ACEASportalGeoServerList === 'undefined')? '':JSON.parse(localStorage.ACEASportalGeoServerList).overlays;
	if (serverList.items.length >= 1)
	{
		localStorage.ACEASportalMenuCount = serverList.items.length;
		localStorage.ACEASportalMenuTemp = '';
		var getCapabilities;

		// Get capabilities of each Geoserver on the server list file
		for (var i=0; i < serverList.items.length; i++)
		{
			var GeoServerWMS = serverList.items[i].URL;
			getCapabilities = OpenLayers.Request.GET({
				url: GeoServerWMS,
				params: 
				{
					SERVICE: serverList.items[i].SERVICE,
					VERSION: serverList.items[i].VERSION,
					REQUEST: serverList.items[i].REQUEST
				},

				// Success: Retrive layers from the response XML and store the layer ionformation in Local Storage for menu contruction when all Geoservers are loaded 
				success: function(request) 
				{
					// Count down the number of loaded Geoservers 
					localStorage.ACEASportalMenuCount--;
					$('#remaining').html(localStorage.ACEASportalMenuCount+' more GeoServer remaining......');
					itemRecords = '';

					// Retrive and convert the getCapability XML into json
					var xml = (request.responseXML)? request.responseXML:request.responseText;
					var serverCapabilities = $.xml2json(xml);
					if (typeof serverCapabilities.Capability !== 'undefined')
					{
						var layers = serverCapabilities.Capability.Layer;
						while (typeof layers.Layer != 'undefined')
						{
							layers = layers.Layer;
						}
						var Url = serverCapabilities.Capability.Request.GetMap.DCPType.HTTP.Get.OnlineResource['xlink:href'];
						// Add feature info control if it is WMS 1.1.1
						if (serverCapabilities.version === '1.1.1')
						{
							addFeatureInfo(Url);
						}
						var tempLayer = new Array();
						if ($.isArray(layers))
						{
							tempLayer = layers;
						}
						else
						{
							tempLayer[0] = layers;
						}
						// Extract and retrive layer information 
						retriveLayer(tempLayer, serverCapabilities.version, Url);
						localStorage.ACEASportalMenuTemp += itemRecords;
					}

					// Reset the layer memu if all Geoservers are loaded 
					if (localStorage.ACEASportalMenuCount === '0')
					{
						if (localStorage.ACEASportalMenuItems !== localStorage.ACEASportalMenuTemp)
						{
							localStorage.ACEASportalMenuItems = localStorage.ACEASportalMenuTemp;
							resetLayer();
						}
					}
				}, 

				// Failure: Count down and reset layer menu if all Geoservers are loaded
				failure: function() {
					localStorage.ACEASportalMenuCount--;
					$('#remaining').html(localStorage.ACEASportalMenuCount+' more GeoServer remaining......');
					OpenLayers.Console.error.apply(OpenLayers.Console, arguments);
					if (localStorage.ACEASportalMenuCount === '0')
					{
						if (localStorage.ACEASportalMenuItems !== localStorage.ACEASportalMenuTemp)
						{
							localStorage.ACEASportalMenuItems = localStorage.ACEASportalMenuTemp;
						}
						resetLayer();
					}
				}
			});
		}
	}
}

// Retrive layers information from the 'layers' array 
function retriveLayer(layers, version, Url)
{
	for (var item = layers.length-1; item>=0; item--)
	{
		// No sub-layer
		if (typeof layers[item].Name !== 'undefined')
		{
			var Name = layers[item].Name;
			var Title = layers[item].Title;
			var Abstract = (layers[item].Abstract)? layers[item].Abstract : '';
			itemRecords += '{"Name":"' + Name + '", "Title":"' + Title + '", "Version":"' + version + '", "Url":"' + Url + '", "Abstract":"' + Abstract + '"},';
		}

		// Has sub-layers
		else
		{
			// Single level
			if (typeof layers[item].Layer.Name !== 'undefined')
			{
				var Name = layers[item].Layer.Name;
				var Title = layers[item].Layer.Title;
				var Abstract = (layers[item].Layer.Abstract)? layers[item].Layer.Abstract : '';
				itemRecords += '{"Name":"' + Name + '", "Title":"' + Title + '", "Version":"' + version + '", "Url":"' + Url + '", "Abstract":"' + Abstract + '"},';
			}

			// Multi level
			else
			{
				subLayers = layers[item];
				while (typeof subLayers.Layer != 'undefined')
				{
					subLayers = subLayers.Layer;
				}
				if (!$.isArray(subLayers))
				{
					subLayers[0] = subLayers; 
				}
				retriveLayer(subLayers, version, Url);
			}
		}
	}
}

// Reset map size, and switch on and off layers for full size screen and mobile device screen 
function resetMapDiv()
{
	$('#footer').hide();

	// Browser with width over 640 pixels
	if ($(window).width() > 640)
	{
		var newWidth = $(window).width()-$('#menu').width();
		$('#map').width(newWidth);
		$('#godiva2').width(newWidth);
	} 

	// Browser with width less than 640 pixels (small screen mobile devices)
	else 
	{
		$('#map').width('100%');
		$('#godiva2').width('100%');
	}

	// turn on/off Title section depending on browser width
	if ($(window).width() < 740){
		if($('#appTitle').is(':visible'))
		{
			$('#appTitle').hide();
		}
	}
	else
	{
		if(!$('#appTitle').is(':visible'))
		{
			$('#appTitle').show();
		}
	}

	// Resize the map and show terms and condition on menu bar for small screen mobile devices
	if ($(window).width() <= $('#menu').width())
	{
		var newHeight = $(window).height()-$('#header').height();
		$('#map').height(newHeight);
		$('#godiva2').height(newHeight);
		$('#content').height($('#map').height()-90);
		$('#iphone-T1').show();
		$('#iphone-T2').show();
		$('#iphone-T3').show();
		$('#iphone-T4').show();
	} 

	// Resize the map and hide layers for small screen mobile devices
	else 
	{
		var newHeight = $(window).height()-$('#header').height()-$('#footer').height()-2;
		$('#map').height(newHeight);
		$('#godiva2').height(newHeight);
		$('#terms').html('ACEAS is part of TERN which is supported by the Australian Government Through the National<br />Collaborative Research Infrastructure Strategy and the Super Science Initiative. <a href="http://aceas-data.science.uq.edu.au/portal/terms.html" target="_blank" data-rel="dialog" data-transition="pop" style="color: #000000;">Terms of Use</a>');
		$('#footer').show();
		$('#iphone-T1').hide();
		$('#iphone-T2').hide();
		$('#iphone-T3').hide();
		$('#iphone-T4').hide();
	}
}

// Create Layer menu using localstorage
function setMenu()
{
	// Load data from latest loaded data 
	if(typeof localStorage.ACEASportalMenuTemp.length > 0)
	{
		var jsonData = localStorage.ACEASportalMenuTemp;
		localStorage.ACEASportalMenuItems = localStorage.ACEASportalMenuTemp
	} 

	// Load data from previous data while new data still loading or fail loading
	else 
	{
		var jsonData = localStorage.ACEASportalMenuItems;
	}

	// Turn on message if there is no data
	if (jsonData.length === 0 )
	{
		$('#initMsg').show();
		return;
	}

	// Construct the layer menu
	else
	{
		// Update Local Storage with lastest data 
		if (typeof localStorage.ACEASportalMenuItems !== 'string')  // '===' ?
		{
			localStorage.ACEASportalMenuItems = localStorage.ACEASportalMenuTemp; 
		}
		var menu = JSON.parse('{"layers":['+jsonData.substring(0,jsonData.length-1)+']}');
		$('#menuList').html('<li id="menuList-divider" data-role="list-divider"> <div>ACEAS Working Group Outcomes<img src="images/help.png" style="position: relative; top: 3px; right: -3px;" title="Select layer(s) from the menu and click on the map to view data information." onclick="alert(\'Select layer(s) from the menu and click on the map to view data information.\')"></div> <p class="ui-li-aside"><input type="button" value="Go to model outputs" onclick="switchMenu();" class="ui-btn-up-b ui-corner-all"><p></li>');
		var orderMenu = [];

		for (var item = menu.layers.length-1; item>=0; item--)
		{
			var project = menu.layers[item].Name.split(':');
			project = project[0];
			project = null; // disable project divider
			orderMenu[item] = project + ' || ' + menu.layers[item].Title + ' || ' + menu.layers[item].Name + ' || ' + menu.layers[item].Version + ' || ' + menu.layers[item].Abstract;
		}

		// Group by Project i.e. Title in XML and order by Layer i.e. Name in XML 
		orderMenu.sort();
		var curProject = orderMenu[orderMenu.length-1].split(' || ');
		curProject = curProject[0];

		// Create copyright section for small screen mobile devices
		$('<li id="iphone-T1"><a href="#terms" data-rel="dialog" data-transition="pop" style="color: #000000;">Terms of Use</a></li>')
		.insertAfter($("#menuList-divider"));
		$('<li id="iphone-T2"><p style="white-space: normal;">ACEAS is part of TERN which is supported by the Australian Government Through the National<br />Collaborative Research Infrastructure Strategy and the Super Science Initiative. <a href="http://aceas-data.science.uq.edu.au/portal/terms.html" target="_blank" data-rel="dialog" data-transition="pop" style="color: #000000;">Terms of Use</a></p></li>')
		.insertAfter($("#menuList-divider"));
		$('<li id="iphone-T3"><p><img src="images/diisr_logo.png" /></p></li>')
		.insertAfter($("#menuList-divider"));
		$('<li id="iphone-T4" data-role="list-divider">&nbsp;</li>')
		.insertAfter($("#menuList-divider"));

		// Create menu item
		for (item = orderMenu.length-1; item>=0; item--)
		{
			var param = orderMenu[item].split(' || ');
			if (curProject !== param[0] && param[0] !== 'undefined')
			{
				$('<li data-theme="a">'+curProject+'</li>')
				.insertAfter($("#menuList-divider"));
				curProject = param[0];
			}
			$('<li><input type="checkbox" id="'+((param[2].replace(':','-SP-')).replace('/','-SP-')).replace(' ','-SP-')+'" onclick="addLayer(\''+param[2]+'\',\''+param[1]+'\',\''+param[3]+'\');" name="'+param[2]+'" id="'+param[2]+'" class="custom" /> <label for="'+param[2]+'" title="'+param[4]+'"> '+param[1]+'</label></li>')
			.insertAfter($("#menuList-divider"));
		}

		// Create project divider  
// disable project divider
/*		if (curProject)
		{
			$('<li data-theme="a">'+curProject+'</li>')
			.insertAfter($("#menuList-divider"));
		}*/
	}

	// Refresh menu style and reset Div size.
	$("#menuList").listview("refresh");
	resetMapDiv();
}

// Extract server list from localstorage and catalog XML of the each server
// Update localstorage with catalog data
function loadCatalogs()
{
	var catalogList = (typeof localStorage.ACEASportalThreddsCatalogList === 'undefined')? '':JSON.parse(localStorage.ACEASportalThreddsCatalogList).overlays;
	var proxy = (OpenLayers.ProxyHost.length > 0)? OpenLayers.ProxyHost:'';

	localStorage.ACEASportalCatalogTemp = '';
	if (catalogList.items.length >= 1)
	{
		localStorage.ACEASportalCatalogCount = catalogList.items.length;
		for (var i=0; i < catalogList.items.length; i++)
		{
			$(document).ready(function()
			{
				$.ajax({
					type: "GET",
					url: proxy + catalogList.items[i].URL + 'catalog.xml',
					proxy: proxy,
					dataType: "xml",

					// Success: Retrive and convert the Thredds catalog XML into json
					success: function(request) 
					{
						var tempDataSet = new Array();
						var xml = $.xml2json(request);
						var dataSet = xml.dataset;
						catalogRecords = '';
						if ($.isArray(dataSet))
						{
							tempDataSet = dataSet;
						}
						else
						{
							tempDataSet[0] = dataSet;
						}
						for (var record = tempDataSet.length-1; record>=0; record--)
						{
							var domain = ($(this)[0].url).replace($(this)[0].proxy,'');
							var Service = tempDataSet[record].serviceName;
							if (Service === 'wms')
							{
								var Name = tempDataSet[record].name;
								var Url = domain.replace('catalog.xml','') + Service + '/' + tempDataSet[record].urlPath;
								catalogRecords += '{"Name":"' + Name + '", "Url":"' + Url + '#"},';
							}
						}
						localStorage.ACEASportalCatalogTemp += catalogRecords;
						if (localStorage.ACEASportalCatalogItems != localStorage.ACEASportalCatalogTemp)
						{
							localStorage.ACEASportalCatalogItems = localStorage.ACEASportalCatalogTemp;
							setCatalog();
						}
					}
				});
			});
		}
	}
}

// Create Thredds catalog menu using localstorage
function setCatalog()
{
	$('#catalogList').html('<li id="catalogList-divider" data-role="list-divider"> ACEAS Projects<p class="ui-li-aside"><input type="button" value="Go to observation data" onclick="switchMenu();" class="ui-btn-up-b ui-corner-all"><p></li>');

	// Load data from latest loaded data 
	if (localStorage.ACEASportalCatalogTemp.length > 0)
	{
		var jsonData = localStorage.ACEASportalCatalogTemp;
		localStorage.ACEASportalCatalogItems = localStorage.ACEASportalCatalogTemp;
	} 

	// Load data from previous data while new data still loading or fail loading
	else 
	{
		var jsonData = localStorage.ACEASportalCatalogItems;
	}

	// Construct the Thredds catalog menu
	if (jsonData.length > 0)
	{
		// Update Local Storage with lastest data 
		if (typeof localStorage.ACEASportalCatalogItems !== 'string')
		{
			localStorage.ACEASportalCatalogItems = localStorage.ACEASportalCatalogTemp; 
		}
		var catalog = JSON.parse('{"layers":['+jsonData.substring(0,jsonData.length-1)+']}');
		var orderCatalog = [];
		for (var item = catalog.layers.length-1; item>=0; item--)
		{
			var project = catalog.layers[item].Name.split(':');
			project = project[0];
			orderCatalog[item] = project + ' || ' + catalog.layers[item].Name + ' || ' + catalog.layers[item].Url;
		}

		// order by Dataset name 
		orderCatalog.sort();
		for (item = orderCatalog.length-1; item>=0; item--)
		{
			var param = orderCatalog[item].split(' || ');
			$('<li><input type="radio" id="'+((param[1].replace(':','-SP-')).replace('/','-SP-')).replace(' ','-SP-')+'" onclick="updateGodiva2(\''+param[2]+'\');" name="thredds" class="custom" /> <label for="'+param[1]+'"> '+param[1]+'</label></li>')
			.insertAfter($("#catalogList-divider"));
		}
	}

	// Refresh menu style and reset Div size.
	$('<li data-theme="a">Model outputs powered by Godiva2</li>').insertAfter($("#catalogList-divider"));
	$("#catalogList").listview("refresh");
	resetMapDiv();
}

// Load selected Thredds catalog to the iFrame
function updateGodiva2(dataSetUrl)
{
	var threddsServer = dataSetUrl.substring(0,dataSetUrl.indexOf('thredds/')+8);

	$('#godiva2').attr('src', threddsServer + 'godiva2/godiva2.html?server=' + dataSetUrl);
}

// Switch maps between Observation Data and Model Outputs 
function switchMenu()
{
	if(!$('#map').is(':visible'))
	{
		$('#godiva2').hide();
		$('#catalogList').hide();
		$('#map').show();
		$('#menuList').show();
		// Openlayer issue: base map not align with tiles image after switch back from Godiva2
              // call following 2 functions to redraw the base map 
		map.layers[0].onMapResize();
		map.layers[0].redraw();
	} 
	else 
	{
		$('#map').hide();
		$('#menuList').hide();
		$('#godiva2').show();
		$('#catalogList').show();
	}
}

// Create Openlayers map object: if no baselayer specified in the server list Json file then use Google Map as default 
function makeMap()
{
	// Set map controls
	var controls = [
		new OpenLayers.Control.Navigation(),
		new OpenLayers.Control.LayerSwitcher(), 
		new OpenLayers.Control.PanZoomBar(),
		new OpenLayers.Control.Scale(),
		new OpenLayers.Control.Attribution()
	];

	// Retrive base map list if exists from Local Storage (last good setting)
	var serverList = JSON.parse(localStorage.ACEASportalGeoServerList).baseLayers;

	// Create base maps if servers are specified
	if ((typeof serverList.items.length !=='undefined') && (serverList.items.length >= 1))
	{
		map = new OpenLayers.Map('map', 
		{
			controls: controls
		});
		for (var i=0; i < serverList.items.length; i++)
		{
			var base = new OpenLayers.Layer.WMS( 
				serverList.items[i].TITLE, serverList.items[i].URL,
				{ 
					styles: '', 
					layers: serverList.items[i].LAYER,
					format: 'image/png', 
					transparent: 'FALSE', 
					version: '1.1.0'
				}, 
				{ 
					isBaseLayer: true, 
					opacity: 1.0, 
					queryable: true, 
					buffer: 1, 
					gutter: 0, 
					transitionEffect: 'resize', 
					wrapDateLine: true 
				} ); 

			map.addLayer(base);
		}
	} 

	// Create the 4 default base maps if no server specified
	else 
	{
		map = new OpenLayers.Map('map', {
			projection: new OpenLayers.Projection("EPSG:900913"),
//			projection: new OpenLayers.Projection("EPSG:4326"),
			units: "m",
			maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
			controls: controls
		});

		var gphy = new OpenLayers.Layer.Google(
			"Terrain",
			{type: G_PHYSICAL_MAP, sphericalMercator: true}
		);
		var gmap = new OpenLayers.Layer.Google(
			"Street Map", 
			{sphericalMercator: true, numZoomLevels: 20}
		);
		var ghyb = new OpenLayers.Layer.Google(
			"Google Hybrid",
			{type: G_HYBRID_MAP, sphericalMercator: true, numZoomLevels: 20}
		);
		var gsat = new OpenLayers.Layer.Google(
			"Satellite",
			{type: G_SATELLITE_MAP, sphericalMercator: true, numZoomLevels: 22}
		);
		map.addLayers([gsat, gphy, gmap]);
	}

	// Bound the map to Australia
	map.setCenter(new OpenLayers.LonLat(135, -27).transform(
		new OpenLayers.Projection("EPSG:4326"),
		map.getProjectionObject()
	), 4);
}

// Create feature info control
function addFeatureInfo(Url)
{
	var info = new OpenLayers.Control.WMSGetFeatureInfo({
		url: Url, 
		title: Url,
		queryVisible: true,
		eventListeners: 
		{
			getfeatureinfo: function(event) 
			{
				map.addPopup(new OpenLayers.Popup.FramedCloud(
					Url, 
					map.getLonLatFromPixel(event.xy),
					null,
					event.text,
					null,
					true
				));
			}
		}
	});
	if (typeof map !== 'undefined')
	{
		var mapControl = map.getControlsByClass("OpenLayers.Control.WMSGetFeatureInfo");
		if (mapControl.length === 0)
		{
			map.addControl(info);
			info.activate();
		}
	}
}

// Add or remove selected overlay to the map
function addLayer(layerName,layerTitle, version)
{
	// Retrive menu information from Local Storage 
	var menu = JSON.parse('{"layers":['+localStorage.ACEASportalMenuItems.substring(0,localStorage.ACEASportalMenuItems.length-1)+']}');
	for (var item = menu.layers.length-1; item>=0; item--)
	{
		if (menu.layers[item].Name === layerName)
		{
			var Url = menu.layers[item].Url;
		}
	}

	// Add layer if WMS 1.1.1
	if (version === '1.1.1')
	{
		var newLayer = new OpenLayers.Layer.WMS(
			layerTitle, Url, 
			{
				layers: layerName,
				version: version,
				transparent: "true", 
				format: "image/png",
				isBaseLayer: false
			}
		);
	} 

	// Add layer if not WMS 1.1.1 (***code curently still has bugs)
	else 
	{
		var newLayer = new OpenLayers.Layer.WMS(
			layerTitle, Url,
			{
				layers: layerName,
				version: version,
				transparent: "true", 
				format: "image/png",
				CRS: 'EPSG:4326',
				isBaseLayer: false
			}
		);

		newLayer.DEFAULT_PARAMS = { 
					service: "WMS",
					version: "1.3.0",
					request: "GetMap",
					styles: "",
					exceptions: "XML",
					format: "image/png",
					crs: "EPSG:4326"
		};
		newLayer.projection = new OpenLayers.Projection('EPSG:4326');
		newLayer.srsKey = 'CRS'; // WMS 1.3.0 uses "CRS=" instead of "SRS="
		newLayer.params.CRS = 'EPSG:4326';
	}

	// Add overlay if layer is selected otherwise remove overlay
	if ($('#'+((layerName.replace(':','-SP-')).replace('/','-SP-')).replace(' ','-SP-')).attr('checked')==='checked')
	{
		var layers = map.getLayersByName(layerTitle);
		if (layers[0] !== layerTitle)
		{ 
			map.addLayer(newLayer);
		}
	} 
	else 
	{
		var layers = map.getLayersByName(layerTitle);
		map.removeLayer(layers[0]);
	}
}

// Reset map to initial setting 
function resetLayer()
{
	if (typeof map !== 'undefined')
	{
		map.destroy();
	}
	setMenu();
//	setCatalog();
	makeMap();
}
 
// Action called by onload event: Check IE version, initialise the map object, load and update GeoServre data, and create the map.       
function init()
{
	$('#godiva2').hide();
	$('#initMsg').hide();
	$('#catalogList').hide();

	// Check for HTML5 compactibility of Internet Explorer
	var browser = [];
	jQuery.each(jQuery.browser, function(i, val) 
	{
		browser[i] = val;
	});
	if ((typeof browser.msie) !== 'undefined' && browser.msie === true && (typeof browser.version) !== 'undefined' &&parseInt(browser.version,10) < '9')
	{
		alert('The portal is developed using HTML5 which your web browser [MSIE:'+browser.version+'] does not support it. Please use a HTML5 compatible web broswer for this portal.');
	}
	
	// Set the map to a fixed position
	resetMapDiv();	
	var menuYloc = null;  
	$(document).ready(function()
	{  
		menuYloc = parseInt($("#map").css("top").substring(0,$("#map").css("top").indexOf("px")));  
		$(window).scroll(function () 
		{  
			var offset = menuYloc+$(document).scrollTop()+"px";  
			$("#map").animate({top:offset},{duration:0,queue:false});  
		});  
	});

	// Create Geoserver layer menu and Thredds Server catalog menu from Local Storage (last good setting)
	setMenu();
	setCatalog();

	// create the map object and reload the geoserver and Thredds servers
	makeMap();
	loadServers();
}
